package net.ib.mtalk.network.clientapi;

import net.ib.mntalk.protocol.Client;
import net.ib.mntalk.protocol.Common;
import net.ib.mtalk.network.NetResultReceiver;
import net.ib.mtalk.network.TcpClient;
import net.ib.mtalk.network.TcpEnvelope;
import net.ib.mtalk.util.MTalkLogWriter;
import android.os.Handler;

/**
 * Client-side API: Ping.Ping<br>
 * 클라이언트 핑을 구현.<br>
 * <br>
 * 이 클래스 내에 기본 수신기가 구현되어 있어서, 기본적으로는 이 클래스가 콜백의 역할을 한다.<br>
 * 그러나 서버의 요청이 있기 전에 {@link Ping#setCallback(NetResultReceiver)}을 호출하여 임의의 콜백을 세팅할 수도 있다.<br>
 * 
 * @author Arngard
 */
public class Ping implements NetResultReceiver.Receiver {

	private static NetResultReceiver defaultCallback = null;
	private static NetResultReceiver callback = null;
	
	public static void setDefault() {
		Ping.defaultCallback = new NetResultReceiver(new Handler(), new Ping());
	}

	/**
	 * 이 호출 다음에 이루어지는 서버 요청은 인자로 지정한 콜백으로 전달된다.
	 * @param callback 목적지가 되는 콜백 객체
	 */
	public static void setCallback(NetResultReceiver callback) {
		Ping.callback = callback;
	}

	/**
	 * {@link Ping#setCallback(NetResultReceiver) setCallback(NetResultReceiver)}으로 세팅한 콜백을 돌려준다.
	 * 세팅하지 않았을 경우, 기본 동작을 하는 콜백 객체를 만들어서 돌려준다.<br>
	 * 네트워크 모듈은 이 메소드의 리턴값을 이용하여 서버 리퀘스트를 전달할 것이다.
	 * @return 목적지가 되는 콜백 객체
	 */
	public static NetResultReceiver getCallback() {
		if (callback == null) {
			MTalkLogWriter.w("clientapi.Ping.getCallback(): client api returned default callback");
			return defaultCallback;
		}
		return callback;
	}

	/**
	 * 이 rpc의 콜백이 지정되지 않은 경우의 기본 구현.<br>
	 * 서버에서 클라이언트로 핑이 오면 Pong을 돌려준다. 내용이 담겨 있었다면 내용을 그대로 돌려준다.
	 * @see net.ib.mtalk.network.NetResultReceiver.Receiver#onNetResult(int, java.lang.Object)
	 */
	@Override
	public void onNetResult(int resultCode, Object sentObject, Object receivedObject) {
		// ping이 왔다. pong을 보내줘야 한다.

		TcpEnvelope received = (TcpEnvelope) receivedObject;
		Client.CPingReq pingReq = (Client.CPingReq)received.getMessage();

		// 뭘 보냈는지 찍어보자
		String toShow = "Ping received - ReqID: " + received.getRequestId();
		if (pingReq.hasOptions()) {
			toShow = toShow + ", Option: " + pingReq.getOptions().toStringUtf8();
		}
		MTalkLogWriter.i("clientapi.Ping.onNetResult(): "+toShow);

		// 응답 객체를 구성한다.
		Client.CPongRes pongRes = new Client.CPongRes();
		pongRes.setResponseCode(Common.SUCCESS);	// 응답 코드 넣고
		if (pingReq.hasOptions()) {	// 내용 있으면
			pongRes.setOptions(pingReq.getOptions());	// 내용 넣고
		}

		TcpEnvelope response = new TcpEnvelope.Builder()
		.setRequestId(received.getRequestId())
		.setType(TcpEnvelope.RESPONSE)
		.setMethodId(received.getMethodId())
		.setMessage(pongRes)
		.build();

		// Response!
		TcpClient.send(response);
	}

	/**
	 * 이 rpc의 콜백이 지정되지 않은 경우의 기본 구현.<br>
	 * @see net.ib.mtalk.network.NetResultReceiver.Receiver#onNetError(int, java.lang.Object)
	 */
	@Override
	public void onNetError(int resultCode, Object sentObject) {
		// do nothing
	}

}
